package globulin;

import globulin.soundFXProccessing.SoundFX;
import jgame.*;
import jgame.platform.JGEngine.*;
import jgame.impl.JGEngineInterface.*;
import java.awt.event.KeyEvent;

/**
 * This class defines the player's ship in the game.
 * @author Sean Pavlichek & Jonathan Horvath
 */
public class Player extends JGObject {

    /**
     * Weapon types that are available to the player
     */
    public static enum WeaponType {
        LASER,
        SEEKER_MISSILE;
    }

    /**
     * The current weapon enabled for the ship.  By default lasers are selected
     */
    private WeaponType currentWeaponType = WeaponType.LASER;
    /**
     * Current strength of the weapon available to the player
     */
    private int currentWeaponLevel = 0;
    private JGObject thrusters;
    /**
     * Keeps track if the ship is invincible
     */
    private boolean isInvincible = true;
    /**
     * Used to blink ship while it is invincible
     */
    private int invincibleFlashIntervalCounter = 0;
    private boolean showShip = true;
    private Globulin gameScreen;

    /**
     * Construct a new player
     * @param parent The game screen. This variable is necessary for many functions.
     * @param x Location of the player on the x axis, the left side starts at zero
     * @param y Location of the player on the y axis, the top starts at zero
     * @param speed The speed of the player movements
     */
    public Player(Globulin parent, double x, double y, double speed) {
        // String name, boolean unique_id, double x, double y, int collisionID,
        // String gfxName, double xSpeed, double ySpeed
        super("player", true, x, y, 0, "playerc", speed, speed);

        gameScreen = parent;

        // Initializes the thrusters
        thrusters = new JGObject("thrusters", true, x + 13, y + 43, 0, "player_thruster_idle", 0, 0);
        thrusters.setAnimPingpong(true);

        colid = Globulin.PLAYER_COLID;

        // 3 seconds of invincibility
        new JGTimer((int) eng.getFrameRate() * 3, true) {

            public void alarm() {
                isInvincible = false;
            }
        };
    }

    /**
     * Handles the move function for the ship. Also handles animation for the
     * ship based on the rate of movement to either side.
     */
    @Override
    public void move() {
        // If the player is trying to move left and there is space
        if (eng.getKey(eng.KeyLeft) && x > xspeed) {
            xdir = -1;
        } // If the player is trying to move right and there is space
        else if (eng.getKey(eng.KeyRight) && x < (eng.pfWidth() - Player.tilewidth)) // Steers the ship right
        {
            xdir = 1;
        } else // Stops the ship's horizontal momentum
        {
            xdir = 0;
        }

        // If the player is trying to move up and there is space
        if (eng.getKey(eng.KeyUp) && y > ((eng.pfHeight() / 2) - yspeed)) {
            ydir = -1;
        } // If the player is trying to move backwards and there is space
        else if (eng.getKey(eng.KeyDown) && y < (eng.pfHeight() - 50)) {
            ydir = 1;
        } else // Stops the ship's reverse motion
        {
            ydir = 0;
        }

        // Update ship graphics
        turnShip();

        // If the player is attempting to fire
        if (eng.getKey(KeyEvent.VK_SPACE)) {
            fireWeapon();
        }
    }

    /**
     * Handles whether or not the ship gets destroyed.
     * @param obj The object that is running into the ship.
     */
    @Override
    public void hit(JGObject obj) {
        // If the object is an enemy ship or missile and the player is not invulnerable
        if (!isInvincible && (obj.colid == Globulin.ENEMY_COLID || obj.colid == Globulin.ENEMY_MISSILE_COLID)) {
            new JGObject("explosion", true, x, y, 0, "explosion", 0, 0, 32);

            gameScreen.score += 5;
            gameScreen.checkScoreForNewLife();

            // Reset the weapon level and switch to laser
            currentWeaponType = WeaponType.LASER;
            currentWeaponLevel = 0;

            thrusters.remove();
            this.remove();
            
        // If the item is a powerup remove the object and increase the weapon level
        } else if (obj.colid == Globulin.POWERUP_COLID) {
            if (currentWeaponType == WeaponType.LASER && currentWeaponLevel < 2) {
                currentWeaponLevel++;
            } else {
                currentWeaponType = WeaponType.SEEKER_MISSILE;
                // 10 second timer seekers
                new JGTimer((int) eng.getFrameRate() * 10, true) {

                    public void alarm() {
                        currentWeaponType = WeaponType.LASER;
                    }
                };
            }

            obj.remove();
        }
    }

    /**
     * Handles the animation of the ship. The ship's picture changes based on
     * its horizontal velocity.
     */
    private void turnShip() {

        // Blink the ship if it is invicible
        if (isInvincible && invincibleFlashIntervalCounter++ > eng.getFrameRate() / 10) {
            setGraphic(null);
            showShip = !showShip;
            invincibleFlashIntervalCounter = 0;
        } else if (!isInvincible) {
            showShip = true;
        }

        // If the ship is visible update the graphics
        if (showShip) {
            switch (xdir) {
                case -1:
                    setGraphic("playerl");
                    break;
                case 0:
                    setGraphic("playerc");
                    break;
                case 1:
                    setGraphic("playerr");
                    break;
                default:
                    break;
            }

            SetThrusterPosition();
        }

        // update the thruster animation
        switch (ydir) {
            case -1:
                thrusters.setAnim("player_thruster_forward");
                break;
            case 0:
            case 1:
                thrusters.setAnim("player_thruster_idle");
                break;
            default:
                break;
        }
    }

    /**
     * Set the thruster position behind the ship.  It changes as the ship moves
     * left and right
     */
    protected void SetThrusterPosition() {
        if (getGraphic().equals("playerl"))
            thrusters.setPos(x + 4, y + 43);
        else if (getGraphic().equals("playerr"))
            thrusters.setPos(x + 9, y + 43);
        else
            thrusters.setPos(x + 14, y + 43);
    }

    /**
     * Logic that handles the firing of weapons
     */
    private void fireWeapon() {
        //Deterine weapon launch locations
        double offsetY = y + 5;
        double leftGunX = x - 5;
        double centerGunX = x + (Player.tilewidth / 2);
        double rightGunX = x + (xdir != 0 ? 25 : 40);

        // Max number of weapons on screen
        int maxWeaponCount = 16;

        // Check the current weapon type and limit the number of weapons that can be fired
        if (currentWeaponType == WeaponType.LASER && eng.countObjects("laser", Globulin.PLAYER_LASER_COLID) < ((currentWeaponLevel + 1) * maxWeaponCount)) {
            // Fires lasers
            switch (currentWeaponLevel) {
                case 0:
                default:
                    new JGObject("laser", true, centerGunX, offsetY, Globulin.PLAYER_LASER_COLID, "laser", 0, -5, -2);
                    break;
                case 1:
                    new JGObject("laser", true, leftGunX, offsetY, Globulin.PLAYER_LASER_COLID, "laser", 0, -5, -2);
                    new JGObject("laser", true, rightGunX, offsetY, Globulin.PLAYER_LASER_COLID, "laser", 0, -5, -2);
                    break;
                case 2:
                    new JGObject("laser", true, leftGunX, offsetY, Globulin.PLAYER_LASER_COLID, "laserl", -2, -5, -2);
                    new JGObject("laser", true, centerGunX, offsetY, Globulin.PLAYER_LASER_COLID, "laser", 0, -5, -2);
                    new JGObject("laser", true, rightGunX, offsetY, Globulin.PLAYER_LASER_COLID, "laserr", 2, -5, -2);
                    break;
            }

        } else if (currentWeaponType == WeaponType.SEEKER_MISSILE && eng.countObjects("missile", Globulin.PLAYER_LASER_COLID) < maxWeaponCount) {
            new SeekerMissile(centerGunX, offsetY, gameScreen);
        }

        // Play missle sound effect
        gameScreen.soundFxThreadPool.execute(new SoundFX(gameScreen, "misslefx"));

        // Resets the fire key so only one missile is fired per key press
        eng.clearKey(KeyEvent.VK_SPACE);
    }
}
